package com.wzq.backend.system;

import com.wzq.backend.service.SecurityService;
import com.wzq.starter.model.UrlAuthority;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;

@Slf4j
@Component
public class MyFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

    @Resource
    private SecurityService securityService;

    //配置文件的加载
    private List<UrlAuthority> urlAuthorities;

    private final AntPathMatcher antPathMatcher = new AntPathMatcher();

    @PostConstruct
    public void init(){
        this.urlAuthorities = securityService.loadAuthorities();
    }


    @Override
    public  Collection<ConfigAttribute>  getAttributes(Object object) throws IllegalArgumentException {
        FilterInvocation fi = (FilterInvocation) object;
        //ADMIN 可以为所欲为
        StringBuilder roles = new StringBuilder("ADMIN");
        String url = fi.getRequestUrl();
        for (UrlAuthority authority : urlAuthorities) {
            if(antPathMatcher.match(authority.getUrlPattern(),url)){
                //如果有，号的就说明是多个角色
                roles.append(",").append(authority.getAuthorities());
                //此处break采取最近匹配原则，第一个被匹配上的权限规则生效，所以最精确的匹配放最前面比较好
                break;
            }
        }
        if("ADMIN".contentEquals(roles)){
            //没匹配的不拦截
            return null;
        }
        return SecurityConfig.createList(roles.toString());
    }


    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }


    @Override
    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }
}
